package com.jacob.androidstudy.javanote;

import java.io.*;

public class $18_IOStream {
	
	/**
	 * java.io.File类是文件和目录路径名的抽象表示形式。
	 * 
	 * File类下有4个常量，分别表示当前OS下的路径分隔符和名称分隔符。所以，为了代码的跨平台兼容性，需要用到分隔符时，要使用这4个常量。
	 * File.pathSeparator - 当前系统下的路径分隔符（字符串）。Windows下为分号，UNIX下为冒号。
	 * File.pathSeparatorChar - 当前系统下的路径分隔符（字符）。Windows下为分号，UNIX下为冒号。
	 * File.separator - 当前系统下的名称分隔符（字符串）。在Windows系统下，它为“\\”；在UNIX系统下，此字段的值为“/”。
	 * File.separatorChar - 当前系统下的名称分隔符（字符）。在Windows系统下，它为“\\”；在UNIX系统下，此字段的值为“/”。
	 * 
	 * File类的实例是不可变的。也就是说，一旦创建，File对象表示的抽象路径名将永不改变。
	 * 
	 * 
	 */
	public void File() {
		/**
		 * 生成一个File对象。
		 */
		File f1 = new File("."+File.separator+"wangchao.txt"); //在Eclipse中，在任何位置引用当前目录“.”，都会被转换成项目的根目录。
		
		/**
		 * 查看路径上的文件或目录是否存在
		 */
		f1.exists();
		
		/**
		 * 查看f1是目录或者是文件
		 */
		f1.isDirectory();
		f1.isFile();
		
		/**
		 * 返回一个字符串数组，每个数组元素对应目录中的每个文件或目录。
		 * 表示目录本身及其父目录的名称不包括在结果中。每个字符串是一个文件名，而不是一条完整路径。
		 * 如果此抽象路径名不表示一个目录，那么此方法将返回 null。
		 */
		f1.list();
		
		/**
		 * 返回一个 File 对象数组，每个数组元素对应目录中的每个文件或目录。
		 * 表示目录本身及其父目录的名称不包括在结果中。得到的每个抽象路径名都是根据此抽象路径名，使用 File(File, String) 构造方法构造的。
		 * 所以，如果此路径名是绝对路径名，那么得到的每个路径名都是绝对路径名；如果此路径名是相对路径名，那么得到的每个路径名都是相对于同一目录的路径名。
		 * 如果此抽象路径名不表示一个目录，那么此方法将返回 null。
		 */
		f1.listFiles();
		
		
		
	}
	
	/**
	 * 按照数据方向，流可以分为输入流和输出流。
	 * 按照数据处理单位，流可以分为字节流（1次读写1个字节）和字符流（1次读写2个字节）。
	 * 按照功能，流可以分为节点流和包装流。
	 * 
	 * 流总结：
	 * 1.java.io包下类的分类。
	 * InputStream是所有输入字节流的父类，OutputStream是所有输出字节流的父类。
	 * Reader是所有输入字符流的父类，Writer是所有输出字符流的父类。
	 * 
	 * 2.读写文件：
	 * 按照字节（1字节）读写文件，使用FileInputStream和FileOutputStream。
	 * 若要将字节流转换成字符流，并指定编码，用InputStreamReader包装FileInputStream、用OutputStreamWriter包装FileOutputStream。
	 * 若要减少IO读写次数，用BufferedInputStream包装FileInputStream、用BufferedOutputStream包装FileOutputStream、用BufferedReader包装InputStreamReader、用BufferedWriter包装OutputStreamWriter。
	 * 将Java基本类型读写到文件中（这样比将基本类型转成String再写要省空间），用DataInputStream包装FileInputStream，用DataOutputStream包装FileOutputStream。
	 * 将Java对象读写到文件中，用ObjectInputStream包装FileInputStream，用ObjectOutputStream包装FileOutputStream。
	 * 
	 * 3.读写内存：
	 * 按照字节读写内存，使用ByteArrayInputStream和ByteArrayOutputStream。
	 * 将Java基本类型读写到内存中（这样比将基本类型转成String再写要省空间），用DataInputStream包装ByteArrayInputStream，用DataOutputStream包装ByteArrayOutputStream。
	 * 将Java对象读写到内存中，用ObjectInputStream包装ByteArrayInputStream，用ObjectOutputStream包装ByteArrayOutputStream
	 * 
	 * 4.Print流（Print流专门用来输出，好处很多。能够输出多种数据类型，不会抛异常，并且能够自动flush）。
	 * 按照字节输出，使用PrintStream。
	 * 按照字符输出，使用PrintWriter。
	 * 
	 * 
	 * 对象序列化
	 * 1.对象若要通过流（ObjectInputStream、ObjectOutputStream）来传输，必须实现java.io.Serializable接口，并声明private static final long serialVersionUID。
	 * 2.对象通过流传输时，只传属性的值，不传方法。若某些属性不需要传的话，可以加上transient关键字。
	 * 3.将对象通过流写入、读出的方式，可以实现对象深复制。
	 * 
	 */
	public void stream() throws IOException {
		
		/**
		 * FileInputStream （输入流 字节流 节点流）一般用来读二进制文件。
		 */
		InputStream is1 = new FileInputStream(new File("."+File.separator+"wangchao.txt")); //用File对象构造FileInputStream对象。
		InputStream is2 = new FileInputStream("."+File.separator+"wangchao.txt"); //用文件路径构造FileInputStream对象。
		
		is1.available(); //返回可以不受阻塞地从此输入流中读取（或跳过）的估计剩余字节数。
		
		is2.read(); //从此输入流中读取1个数据字节并返回。如果没有输入可用，则此方法将阻塞；如果已到达文件末尾，则返回-1。
//		is1.read(byte[] b); //从此输入流中读取若干个字节，存入b数组中。直到b数组存满，或文件结束为止。返回存入b数组的总字节数，如果由于已到达此文件的末尾而不再有数据，则返回-1。
//		is2.read(byte[] b, 5, 10); //从此输入流中读取10个字节，从下标5开始存入b数组中。返回存入b数组的总字节数，如果由于已到达此文件的末尾而不再有数据，则返回-1。
		
		is1.skip(10); //从输入流中跳过并丢弃10个字节的数据。返回实际跳过的字节数。
		
		is1.close();is2.close(); //关闭此文件输入流并释放与此流有关的所有系统资源。如果此流有一个与之关联的通道，则关闭该通道。
		
		/**
		 * FileOutputStream（输出流 字节流 节点流）一般用来写二进制文件。
		 */
		OutputStream os1 = new FileOutputStream(new File("."+File.separator+"wangchao.txt")); //用File对象构造FileOutputStream对象。
		OutputStream os2 = new FileOutputStream("."+File.separator+"wangchao.txt"); //用文件路径构造FileOutputStream对象。
		
		os1.write(10); //将10强转换为byte，然后写入此输出流。
		
		os2.write("byte数组".getBytes()); //将传入的byte数组写入此输出流。此方法的常规协定是：应该与调用 write(b, 0, b.length) 的效果完全相同。
		
		os1.write("byte数组".getBytes(), 0, 5); //将传入的byte数组中，从下标0开始的5个元素写入此输出流。
		
		os2.flush(); //刷新此输出流并强制写出所有缓冲的输出字节。
		
		os1.close();os2.close(); //关闭此输出流并释放与此流有关的所有系统资源。
		
		
		/**
		 * RandomAccessFile（输入输出流 字节流 字符流 节点流）一般用来对文件同时进行读写。
		 */
		RandomAccessFile raf1=new RandomAccessFile(new File("."+File.separator+"wangchao.txt"),"r"); //用File对象构造RandomAccessFile对象，第二个参数表示以只读方式打开文件。
		RandomAccessFile raf2=new RandomAccessFile("."+File.separator+"wangchao.txt","rw"); //用文件路径构造RandomAccessFile对象，第二个参数表示以读写方式打开文件。
		
		
		raf1.length(); //返回文件的长度。
		
		raf1.read(); //从此文件中读取1个数据字节。以整数形式返回此字节，范围在0到255。如果已到达文件的末尾，则返回-1。
//		raf2.read(byte[] b); //从此文件中读取若干个字节，存入b数组中。直到b数组存满，或文件结束为止。返回存入b数组的总字节数，如果由于已到达此文件的末尾而不再有数据，则返回-1。
//		raf1.read(byte[] b, 5, 10); //从此文件中读取10个字节，从下标5开始存入b数组中。返回存入b数组的总字节数，如果由于已到达此文件的末尾而不再有数据，则返回-1。
		
		raf2.readChar(); //从文件的当前文件指针开始读取两个字节，并按照char类型返回。
		
		/**
		 * DataInputStream（输入流 包装流）一般用来将InputStream节点流包装成Java中的基本类型进行read。
		 */
		DataInputStream dis = new DataInputStream(is1); //将is1包装成DataInputStream对象。
		
		dis.readBoolean();
		dis.readByte();
		dis.readDouble();
		dis.readFloat();
		dis.readInt();
		dis.readLong();
		
		dis.close();
		
		/**
		 * DataOutputStream（输出流 包装流）一般用来将OutputStream节点流包装成Java中的基本类型进行write。
		 */
		DataOutputStream dos = new DataOutputStream(os1); //将os1包装成DataOutputStream对象。
		
		dos.writeBoolean(true);
		dos.writeByte(10);
		dos.writeChar(10);
		dos.writeDouble(10.0);
		dos.writeFloat(10.0f);
		dos.writeInt(10);
		dos.writeLong(10l);
		
		dos.close();
		
	}
	
	


}
